import { useCallback } from 'react'
// import ELK from 'elkjs/lib/elk.bundled.js'
import dagre from '@dagrejs/dagre';
import {
  useReactFlow,
  useStoreApi,
} from 'reactflow'
import { cloneDeep } from 'lodash-es'
import type {
  Edge,
  Node,
} from '../types'
import { useWorkflowStore } from '../store'
import { AUTO_LAYOUT_OFFSET } from '../constants'
import { useNodesSyncDraft } from './use-nodes-sync-draft'

const layoutOptions = {
  'elk.algorithm': 'layered',
  'elk.direction': 'RIGHT',
  'elk.layered.spacing.nodeNodeBetweenLayers': '60',
  'elk.spacing.nodeNode': '40',
  'elk.layered.nodePlacement.strategy': 'SIMPLE',
}

// const elk = new ELK()
const dagreGraph = new dagre.graphlib.Graph().setDefaultEdgeLabel(() => ({}));

export const getLayoutedNodes = async (nodes: Node[], edges: Edge[]) => {
  const direction = 'LR';

  const nodeWidth = 172;
  const nodeHeight = 36;

  const isHorizontal = direction === 'LR';
  dagreGraph.setGraph({ rankdir: direction });

  nodes.forEach((node) => {
    dagreGraph.setNode(node.id, { width: node.width ?? 150, height: node.height ?? 50 });
  });

  edges.forEach((edge) => {
    dagreGraph.setEdge(edge.source, edge.target);
  });

  dagre.layout(dagreGraph);

  const newNodes = nodes.map((node) => {
    const nodeWithPosition = dagreGraph.node(node.id);
    const newNode = {
      ...node,
      targetPosition: isHorizontal ? 'left' : 'top',
      sourcePosition: isHorizontal ? 'right' : 'bottom',
      position: {
        x: nodeWithPosition.x - nodeWidth / 2,
        y: nodeWithPosition.y - nodeHeight / 2,
      },
    };

    return newNode;
  });

  return {
    layoutedNodes: newNodes,
  }

  // const graph = {
  //   id: 'root',
  //   layoutOptions,
  //   children: nodes.map((n) => {
  //     return {
  //       ...n,
  //       width: n.width ?? 150,
  //       height: n.height ?? 50,
  //       targetPosition: 'left',
  //       sourcePosition: 'right',
  //     }
  //   }),
  //   edges: cloneDeep(edges),
  // }

  // const layoutedGraph = await elk.layout(graph as any)
  // const layoutedNodes = nodes.map((node) => {
  //   const layoutedNode = layoutedGraph.children?.find(
  //     lgNode => lgNode.id === node.id,
  //   )

  //   return {
  //     ...node,
  //     position: {
  //       x: (layoutedNode?.x ?? 0) + AUTO_LAYOUT_OFFSET.x,
  //       y: (layoutedNode?.y ?? 0) + AUTO_LAYOUT_OFFSET.y,
  //     },
  //   }
  // })

  // return {
  //   layoutedNodes,
  // }
}

export const useNodesLayout = () => {
  const store = useStoreApi()
  const reactflow = useReactFlow()
  const workflowStore = useWorkflowStore()
  const { handleSyncWorkflowDraft } = useNodesSyncDraft()

  const handleNodesLayout = useCallback(async () => {
    workflowStore.setState({ nodeAnimation: true })
    const {
      getNodes,
      edges,
      setNodes,
    } = store.getState()
    const { setViewport } = reactflow
    const {
      layoutedNodes,
    } = await getLayoutedNodes(getNodes(), edges)

    setNodes(layoutedNodes)
    const zoom = 0.7
    setViewport({
      x: 0,
      y: 0,
      zoom,
    })
    setTimeout(() => {
      handleSyncWorkflowDraft()
    })
  }, [store, reactflow, handleSyncWorkflowDraft, workflowStore])

  return {
    handleNodesLayout,
  }
}
